package com.example.test.service;

import com.example.test.model.OrderRequest;
import org.springframework.stereotype.Service;
import org.springframework.scheduling.annotation.Async;
import org.springframework.beans.factory.annotation.Qualifier;
import java.util.concurrent.Executor;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * 本服务类演示了如何在Spring项目中结合CompletableFuture和自定义线程池实现多种异步编程场景。
 * 包括：基本异步、链式调用、任务组合、异常处理、超时处理、实际业务流程等。
 * 线程池通过构造器注入，确保所有异步任务统一使用AsyncConfig中配置的线程池。
 */
@Service
public class CompletableFutureService {

    // 随机数生成器，用于模拟异常等场景
    private static final Random random = new Random();
    // 注入Spring容器中定义的线程池（taskExecutor），用于所有异步任务
    private final Executor taskExecutor;

    // 通过 @Qualifier("taskExecutor") 注解指定使用哪个线程池，把AsyncConfig中提前创建好的线程池注入进来
    // 为了让下面用CompletableFuture.runAsync()和CompletableFuture.supplyAsync()去执行异步任务时使用的是这一个指定的线程池，而不是使用默认线程池。
    public CompletableFutureService(@Qualifier("taskExecutor") Executor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }

    /**
     * 演示1：基本异步执行
     * 展示runAsync（无返回值）和supplyAsync（有返回值）的用法。
     * 两个任务串行执行，最终返回第二个任务的结果。
     */
    public CompletableFuture<String> basicAsyncDemo() {
        // 方式1：使用 runAsync 执行无返回值的任务
        CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getName());
            System.out.println("异步任务1：正在处理订单...");
            sleep(1000);
            System.out.println("异步任务1：订单处理完成");
        }, taskExecutor);

        // 方式2：使用 supplyAsync 执行有返回值的任务
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getName());
            System.out.println("异步任务2：正在检查库存...");
            sleep(1500);
            return "库存充足";
        }, taskExecutor);

        // 等待第一个任务完成后，继续执行第二个任务，并返回其结果
        return future1.thenCompose(v -> future2);

        /*
         * 补充说明：如果没有了return future1.thenCompose(v -> future2); 这一行会怎么样？
         * 当调用basicAsyncDemo()方法时，会执行以下步骤：
         * 创建一个 CompletableFuture 对象future1，用于执行第一个异步任务。
         * 创建一个 CompletableFuture 对象future2，用于执行第二个异步任务。
         * 这两行代码会立刻提交两个异步任务到线程池中，也就是说，只要执行到这两行，任务就已经被线程池调度，开始异步执行了。
         * 但是，由于方法没有返回值，调用者拿不到任何 CompletableFuture 对象，也无法等待、获取结果或做后续处理。
         * return 语句的作用是：让调用者可以拿到一个 CompletableFuture，用于后续链式操作、等待结果或异常处理等。
         * 如果没有return，调用者无法感知和控制这些异步任务的执行和结果。如果你只是想"触发"异步任务，不关心结果，可以不 return。
         * 如果你希望调用者能拿到异步任务的结果或做进一步处理，应该 return 一个 CompletableFuture。
         */
    }

    /**
     * 演示2：链式调用
     * 展示thenApply的链式调用，模拟多步业务处理流程。
     */
    public CompletableFuture<String> chainDemo() {
        return CompletableFuture
            .supplyAsync(() -> {
                System.out.println("当前线程：" + Thread.currentThread().getName());
                System.out.println("步骤1：获取用户信息");
                sleep(500);
                return "用户ID: 12345";
            }, taskExecutor)
            .thenApply(userInfo -> {
                System.out.println("当前线程：" + Thread.currentThread().getName());
                System.out.println("步骤2：验证用户信息: " + userInfo);
                sleep(500);
                return userInfo + " (已验证)";
            })
            .thenApply(verifiedUser -> {
                System.out.println("当前线程：" + Thread.currentThread().getName());
                System.out.println("步骤3：计算用户等级: " + verifiedUser);
                sleep(500);
                return verifiedUser + " - VIP用户";
            })
            .thenApply(finalResult -> {
                System.out.println("当前线程：" + Thread.currentThread().getName());
                System.out.println("步骤4：处理完成: " + finalResult);
                return finalResult;
            });
            //这四个步骤是同步处理而不是异步处理的，也就是一个任务执行完，再执行下一个任务，并且用的都是同一个线程
    }

    /**
     * 演示3：组合多个异步任务
     * 并行执行多个任务，并将结果合并。
     */
    public CompletableFuture<String> combineDemo() {
        // 并行执行多个任务
        CompletableFuture<String> checkInventory = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getName());
            System.out.println("并行任务1：检查库存");
            sleep(1000);
            return "库存充足";
        }, taskExecutor);

        CompletableFuture<String> checkUser = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getName());
            System.out.println("并行任务2：验证用户");
            sleep(1200);
            return "用户有效";
        }, taskExecutor);

        CompletableFuture<String> calculatePrice = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getName());
            System.out.println("并行任务3：计算价格");
            sleep(800);
            return "价格: ¥299";
        }, taskExecutor);

        // 合并所有任务的结果
        return checkInventory
            .thenCombine(checkUser, (inventory, user) -> inventory + ", " + user)
            .thenCombine(calculatePrice, (combined, price) -> combined + ", " + price);
        //最终返回给前端的值为：库存充足, 用户有效, 价格: ¥299
        //注意：这里三个任务是并行执行的，也就是每个任务使用的都是不同的线程，所以最终返回给前端的值是三个任务的结果的拼接，而不是串行执行的。
    }

    /**
     * 演示4：异常处理
     * 展示thenApply、exceptionally、handle等方法的用法，模拟异常场景。
     *
     * 详细说明：
     * 这个方法演示了如何在CompletableFuture的异步任务链中进行异常处理，
     * 并展示了thenApply、exceptionally、handle三种常用的处理方式。
     * 执行流程如下：
     * 1. supplyAsync：在自定义线程池中异步执行一个任务，随机决定是否抛出异常。
     *    - 如果抛出异常，后续链路会进入异常分支；否则返回"任务成功完成"。
     * 2. thenApply：只处理正常结果，拼接"(已处理)"。
     * 3. exceptionally：只处理异常，返回补偿结果。
     * 4. handle：无论正常还是异常都会执行，做最终的兜底处理。
     * 最终返回的CompletableFuture<String>，其结果可能是：
     *   - "任务成功完成 (已处理)"（正常流程）
     *   - "任务失败，使用默认值"（exceptionally补偿）
     *   - "异常处理完成"（handle里处理异常）
     */
    public CompletableFuture<String> exceptionHandlingDemo() {
        return CompletableFuture
            .supplyAsync(() -> {
                // 第一步：supplyAsync
                // 在自定义线程池中异步执行一个任务，随机抛出异常或返回正常结果
                System.out.println("当前线程：" + Thread.currentThread().getName());
                System.out.println("执行可能出错的任务...");
                sleep(500);
                if (random.nextBoolean()) {
                    throw new RuntimeException("模拟的随机错误");
                }
                return "任务成功完成";
            }, taskExecutor)
            .thenApply(result -> {
                // 第二步：thenApply
                // 如果上一步没有异常，则进入thenApply，处理正常结果
                System.out.println("当前线程：" + Thread.currentThread().getName());
                System.out.println("处理结果: " + result);
                return result + " (已处理)";
            })
            .exceptionally(throwable -> {
                // 第三步：exceptionally
                // 如果前面任何一步出现异常，会进入exceptionally，返回补偿结果
                System.out.println("当前线程：" + Thread.currentThread().getName());
                System.out.println("捕获异常: " + throwable.getMessage());
                return "任务失败，使用默认值";
            })
            .handle((result, throwable) -> {
                // 第四步：handle
                // 无论前面是正常还是异常都会执行，做最终的兜底处理
                System.out.println("当前线程：" + Thread.currentThread().getName());
                if (throwable != null) {
                    System.out.println("handle方法处理异常: " + throwable.getMessage());
                    return "异常处理完成";
                } else {
                    System.out.println("handle方法处理成功结果: " + result);
                    return result;
                }
            });
    }

    /**
     * 演示5：超时处理
     * 通过anyOf实现超时控制，哪个任务先完成就返回哪个结果。
     */
    public CompletableFuture<String> timeoutDemo() {
        // 模拟一个慢任务
        CompletableFuture<String> slowTask = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getName());
            System.out.println("开始执行慢任务...");
            sleep(3000); // 3秒
            return "慢任务完成";
        }, taskExecutor);

        // 创建超时任务
        CompletableFuture<String> timeoutTask = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getName());
            sleep(1000); // 1秒超时
            return "任务超时";
        }, taskExecutor);

        // 谁先完成就用谁的结果
        return CompletableFuture.anyOf(slowTask, timeoutTask)
            .thenApply(result -> (String) result);
    }

    /**
     * 演示6：实际订单处理流程
     * 通过多个异步任务串联，模拟真实业务场景下的订单处理。
     * 包括：检查库存、验证用户、计算价格、扣减库存、生成订单、发送通知。
     * 每一步都可能提前返回失败结果。
     * 每一步都用 thenCompose 串联，保证前一步成功后才执行下一步，实现严格的业务顺序。
     * 每一步都判断是否成功，一旦失败就用 CompletableFuture.completedFuture 立即返回失败结果，后续步骤不会再执行。
     * 最后一步发送通知是用 CompletableFuture.runAsync 异步触发的，不影响主流程的返回速度。
     * 这是一个典型的异步串行业务编排案例。
     */
    public CompletableFuture<OrderResult> processOrder(OrderRequest orderRequest) {
        // 构造订单对象
        Order order = new Order(
            orderRequest.getOrderId(),
            orderRequest.getProductName(),
            orderRequest.getQuantity(),
            orderRequest.getPrice()
        );

        // 串联各个业务步骤，遇到失败则提前返回
        return CompletableFuture
            .supplyAsync(() -> checkInventory(order), taskExecutor)
            .thenCompose(inventoryResult -> {
                if (!inventoryResult.isSuccess()) {
                    return CompletableFuture.completedFuture(
                        new OrderResult(false, "库存不足: " + inventoryResult.getMessage())
                    );
                }
                return CompletableFuture.supplyAsync(() -> validateUser(order), taskExecutor)
                    .thenCompose(userResult -> {
                        if (!userResult.isSuccess()) {
                            return CompletableFuture.completedFuture(
                                new OrderResult(false, "用户验证失败: " + userResult.getMessage())
                            );
                        }
                        return CompletableFuture.supplyAsync(() -> calculatePrice(order), taskExecutor)
                            .thenCompose(priceResult -> {
                                if (!priceResult.isSuccess()) {
                                    return CompletableFuture.completedFuture(
                                        new OrderResult(false, "价格计算失败: " + priceResult.getMessage())
                                    );
                                }
                                return CompletableFuture.supplyAsync(() -> deductInventory(order), taskExecutor)
                                    .thenCompose(inventoryResult2 -> {
                                        if (!inventoryResult2.isSuccess()) {
                                            return CompletableFuture.completedFuture(
                                                new OrderResult(false, "库存扣减失败: " + inventoryResult2.getMessage())
                                            );
                                        }
                                        return CompletableFuture.supplyAsync(() -> generateOrder(order), taskExecutor)
                                            .thenApply(orderResult -> {
                                                if (!orderResult.isSuccess()) {
                                                    return new OrderResult(false, "订单生成失败: " + orderResult.getMessage());
                                                }
                                                // 异步发送通知，不等待结果
                                                CompletableFuture.runAsync(() -> sendNotification(order), taskExecutor);
                                                return new OrderResult(true, orderResult.getMessage());
                                            });
                                    });
                            });
                    });
            });
    }

    /**
     * 批量处理订单
     * 将每个订单处理任务转为CompletableFuture，最后收集所有结果。
     */
    public CompletableFuture<List<OrderResult>> batchProcessOrders(List<OrderRequest> orderRequests) {
        
        List<CompletableFuture<OrderResult>> futures = orderRequests.stream()// 遍历传入的订单请求列表 orderRequests，将每个订单转换为 CompletableFuture
            .map(this::processOrder)//对每个订单请求，调用 processOrder 方法（这是一个返回 CompletableFuture<OrderResult> 的异步方法）。
            .collect(Collectors.toList());

        // 等待所有订单处理完成，收集结果
        return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
            .thenApply(v -> futures.stream()
                .map(CompletableFuture::join)
                .collect(Collectors.toList()));
    }

    // 模拟业务方法
    private ProcessResult checkInventory(Order order) {
        System.out.println("检查库存: " + order.getProductName() + " x" + order.getQuantity());
        sleep(500);
        if (order.getQuantity() <= 10) {
            return new ProcessResult(true, "库存充足");
        } else {
            return new ProcessResult(false, "库存不足");
        }
    }

    private ProcessResult validateUser(Order order) {
        System.out.println("验证用户信息");
        sleep(300);
        return new ProcessResult(true, "用户验证通过");
    }

    private ProcessResult calculatePrice(Order order) {
        System.out.println("计算订单价格");
        sleep(400);
        double totalPrice = order.getPrice() * order.getQuantity();
        if (totalPrice > 10000) {
            totalPrice *= 0.9; // 大额订单9折
        }
        return new ProcessResult(true, "价格计算完成: ¥" + totalPrice);
    }

    private ProcessResult deductInventory(Order order) {
        System.out.println("扣减库存");
        sleep(200);
        return new ProcessResult(true, "库存扣减成功");
    }

    private ProcessResult generateOrder(Order order) {
        System.out.println("生成订单");
        sleep(300);
        return new ProcessResult(true, "订单生成成功: " + order.getOrderId());
    }

    private void sendNotification(Order order) {
        System.out.println("发送订单通知");
        sleep(100);
        System.out.println("通知发送完成");
    }

    private void sleep(long milliseconds) {
        try {
            Thread.sleep(milliseconds);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    // 数据模型类
    public static class Order {
        private String orderId;
        private String productName;
        private int quantity;
        private double price;

        public Order(String orderId, String productName, int quantity, double price) {
            this.orderId = orderId;
            this.productName = productName;
            this.quantity = quantity;
            this.price = price;
        }

        // Getters
        public String getOrderId() { return orderId; }
        public String getProductName() { return productName; }
        public int getQuantity() { return quantity; }
        public double getPrice() { return price; }
    }

    public static class ProcessResult {
        private boolean success;
        private String message;

        public ProcessResult(boolean success, String message) {
            this.success = success;
            this.message = message;
        }

        public boolean isSuccess() { return success; }
        public String getMessage() { return message; }

        @Override
        public String toString() {
            return success ? "成功: " + message : "失败: " + message;
        }
    }

    public static class OrderResult {
        private boolean success;
        private String message;

        public OrderResult(boolean success, String message) {
            this.success = success;
            this.message = message;
        }

        public boolean isSuccess() { return success; }
        public String getMessage() { return message; }

        @Override
        public String toString() {
            return success ? "订单处理成功: " + message : "订单处理失败: " + message;
        }
    }
} 